import logging
import asyncio
import zlib
import json
import telnetlib3
from telnetlib3.telopt import CHARSET, GMCP
import re
from collections import deque

# 定义MSSP和MSP协议选项代码
MSSP = b'F'  # 70
MSP = b'Z'   # 90
# MCCP2压缩协议选项代码
MCCP2 = b'V'  # 86

# MSSP协议中的特殊字节
MSSP_VAR = b'\x01'  # 变量名开始
MSSP_VAL = b'\x02'  # 变量值开始

class ExtensionWriter():
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 初始化MCCP2相关属性
        self.mccp2_compressing = False
        self.decompressor = None
        self.compressed_buffer = bytearray()
    
    def handle_will(self, option):
        """
        重写handle_will方法，拦截CHARSET、GMCP、MSSP、MCCP2和MSP协商
        
        Args:
            option (bytes): 选项代码
        """

        # 特别处理CHARSET、GMCP、MSSP、MCCP2和MSP选项
        if option == CHARSET or option == GMCP:
            # 发送DO，同意CHARSET和GMCP协商
            self.log.debug("CHARSET或GMCP正确发送DO CHARSET/GMCP")
            self.iac(telnetlib3.DO, option)
            return True
        elif option == MSSP or option == MSP:
            # 发送DO，同意MSSP和MSP协商
            option_name = "MSSP" if option == MSSP else "MSP"
            self.log.debug(f"服务器请求启用{option_name}协议，客户端同意")
            self.iac(telnetlib3.DO, option)
            
            # 对于MSSP，我们可能需要发送请求获取服务器信息
            if option == MSSP:
                # 可以在这里添加发送MSSP请求的代码
                # self.iac(telnetlib3.SB, MSSP, b'\x01')  # 请求服务器信息
                pass
            return True
        elif option == MCCP2:
            # 发送DO，同意MCCP2协商
            self.log.debug("服务器请求启用MCCP2协议，客户端同意")
            self.iac(telnetlib3.DO, option)
            return True
        
        # 对于其他选项，调用父类方法处理
        return super().handle_will(option)

    def handle_do(self, option):
        """
        重写handle_do方法，拦截MSSP和MSP协商
        
        Args:
            option (bytes): 选项代码
        """
        # 特别处理MSSP和MSP选项
        if option == MSSP or option == MSP:
            option_name = "MSSP" if option == MSSP else "MSP"
            self.log.debug(f"服务器请求启用{option_name}协议，客户端同意")
            self.iac(telnetlib3.WILL, option)
            return True
        elif option == MCCP2:
            # 发送WILL，同意MCCP2协商
            self.log.debug("服务器请求启用MCCP2协议，客户端同意")
            self.iac(telnetlib3.WILL, option)
            return True
            
        # 对于其他选项，调用父类方法处理
        return super().handle_do(option)

    def handle_subnegotiation(self, buf):
        """
        重写handle_subnegotiation方法，添加对MSSP子协商的支持
        
        Args:
            buf (collections.deque): 子协商数据缓冲区
        """
        if not buf:
            raise ValueError("SE: buffer empty")
        if buf[0] == telnetlib3.theNULL:
            raise ValueError("SE: buffer is NUL")
        # 修复：允许长度为1的缓冲区（MCCP2子协商开始）
        if len(buf) < 1:
            raise ValueError("SE: buffer too short: {!r}".format(buf))

        cmd = buf[0]
        if self.pending_option.enabled(telnetlib3.SB + cmd):
            self.pending_option[telnetlib3.SB + cmd] = False
        else:
            self.log.debug("[SB + {}] unsolicited".format(telnetlib3.name_command(cmd)))

        # 处理MSSP子协商
        if cmd == MSSP:
            self._handle_sb_mssp(buf)
            return
        elif cmd == MSP:
            self._handle_sb_msp(buf)
            return
        elif cmd == MCCP2:
            # 处理MCCP2子协商（压缩开始标志）
            self.log.debug("MCCP2子协议处理")
            # 设置压缩标志
            self.mccp2_compressing = True
            # 初始化zlib解压缩器，使用不检查zlib头的模式
            self.decompressor = zlib.decompressobj()
            # 初始化压缩数据缓冲区
            self.compressed_buffer = bytearray()
            self.log.debug("MCCP2解压器已初始化，参数为默认")
            return
            
        # 对于其他选项，调用父类方法处理
        try:
            super().handle_subnegotiation(buf)
        except ValueError as e:
            # 如果父类无法处理该子协商，我们只记录日志而不抛出异常
            self.log.debug(f"未处理的子协商: {e}")

    def feed_byte(self, byte):
        """
        重写feed_byte方法以处理MCCP2压缩数据
        
        Args:
            byte (bytes): 单字节数据
            
        Returns:
            bool: 是否为带内数据
        """
        # 确保byte是正确的类型 (telnetlib3要求是int类型，0-255)
        if isinstance(byte, bytes):
            if len(byte) > 1:
                # 如果是一串字节，需要逐个处理，返回最后一个字节的处理结果
                result = True
                for b in byte:
                    result = self.feed_byte(b)  # 传入整数
                return result
            else:
                # 单个字节，转换为整数
                byte = byte[0]
        elif not isinstance(byte, int):
            # 不支持的类型，使用默认处理
            return super().feed_byte(byte)
        
        # 如果启用了MCCP2压缩，则解压缩数据
        if self.mccp2_compressing and self.decompressor:
            
            # 将字节添加到压缩缓冲区
            self.compressed_buffer.extend(byte)
            
            # 记录单个字节（仅记录前几个用于调试）
            if len(self.compressed_buffer) <= 5:
                self.log.debug(f"收到压缩字节: {byte}")
            
            # 每收到一个字节就尝试解压，确保每个字节解压后都能被解析器识别
            # 尝试解压缩缓冲区中的所有数据（流式解压）
            compressed_bytes = bytes(self.compressed_buffer)
            self.log.debug(f"尝试解压 {len(compressed_bytes)} 字节数据: {compressed_bytes[:32]}")
            
            try:
                decompressed = self.decompressor.decompress(compressed_bytes)
                
                # 记录解压后的数据
                self.log.debug(f"解压成功，解压后数据长度: {len(decompressed)}, 数据: {decompressed[:64] if decompressed else b''}")
                self.log.debug(f"未消费数据长度: {len(self.decompressor.unconsumed_tail)}")
                
                # 清空已处理的压缩数据（无论是否还有未消费数据）
                self.compressed_buffer.clear()
                
                # 如果有未消费的数据，将其放回缓冲区
                if self.decompressor.unconsumed_tail:
                    self.compressed_buffer.extend(self.decompressor.unconsumed_tail)
                
                # 将解压缩后的数据重新送入处理流程
                self.log.debug(f"将 {len(decompressed)} 字节解压数据重新注入处理流程")
                result = True
                for b in decompressed:
                    result = super().feed_byte(bytes([b]))
                    self.log.debug(f"处理解压字节 {bytes([b])} 结果: {result}")
                self.log.debug("完成解压数据注入")
                return result  # 返回最后一个字节的处理结果
            except zlib.error as e:
                self.log.error(f"MCCP2解压缩错误: {e}")
                # 解压缩失败时，清空缓冲区并使用原始数据
                self.compressed_buffer.clear()
                return super().feed_byte(byte)

        # 默认处理
        return super().feed_byte(byte)

    def _handle_sb_mssp(self, buf):
        """
        处理MSSP子协商数据
        
        Args:
            buf (collections.deque): MSSP数据包
        """
        self.log.debug(f"收到MSSP子协商数据: {list(buf)}")
        
        # 解析MSSP数据
        # MSSP格式: MSSP_VAR KEY MSSP_VAL VALUE MSSP_VAR KEY MSSP_VAL VALUE ...
        buf_copy = list(buf)[1:]  # 移除第一个字节(MSSP选项)
        
        mssp_data = {}
        current_key = None
        current_value = []
        is_key = False
        is_value = False
        
        i = 0
        while i < len(buf_copy):
            byte = buf_copy[i]
            
            if byte == MSSP_VAR:
                # 新的键开始
                if current_key is not None and current_value:
                    # 保存之前的键值对
                    key_str = b''.join(current_value).decode('utf-8', errors='ignore')
                    mssp_data[current_key] = key_str
                
                current_key = None
                current_value = []
                is_key = True
                is_value = False
            elif byte == MSSP_VAL:
                # 值开始
                if current_key is None and current_value:
                    # 保存键
                    current_key = b''.join(current_value).decode('utf-8', errors='ignore')
                
                current_value = []
                is_key = False
                is_value = True
            else:
                # 数据字节
                current_value.append(byte)
            
            i += 1
        
        # 保存最后一个键值对
        if current_key is not None and current_value:
            value_str = b''.join(current_value).decode('utf-8', errors='ignore')
            mssp_data[current_key] = value_str
        
        self.log.debug(f"MSSP数据解析完成: {mssp_data}")
        
        # 显示服务器状态信息
        if mssp_data:
            status_info = "服务器状态信息:\n"
            for key, value in mssp_data.items():
                status_info += f"  {key}: {value}\n"
            self.log.info(status_info)

    def _handle_sb_msp(self, buf):
        """
        处理MSP子协商数据
        
        Args:
            buf (collections.deque): MSP数据包
        """
        self.log.debug(f"收到MSP子协商数据: {list(buf)}")

    def handle_ga(self, cmd):
        """Handle IAC Go-Ahead (GA)."""
        self.log.debug("收到GA信号，可以推送消息")

    def _handle_sb_gmcp(self, buf):
        """
        处理GMCP子协商数据
        
        Args:
            buf (list): GMCP数据包
        """
        try:
            gmcp_data = b''.join(buf)
            self.log.debug(f"收到GMCP数据: {gmcp_data}")
            
            # 解析GMCP数据
            gmcp_str = gmcp_data.decode('utf-8', errors='ignore')
            
            # 使用正则表达式分离包名和JSON数据
            match = re.match(r'^([^ ]+) (.*)$', gmcp_str)
            if match:
                package_name = match.group(1)
                json_data = match.group(2)
                
                self.log.debug(f"GMCP包名: {package_name}")
                self.log.debug(f"GMCP数据: {json_data}")
                
                # 解析JSON数据
                try:
                    data = json.loads(json_data)
                    self.log.debug(f"解析后的GMCP数据: {data}")
                    
                    # 根据包名处理不同类型的数据
                    if package_name == "GMCP.Move":
                        self._handle_move_data(data)
                    # 可以添加更多包类型的处理
                except json.JSONDecodeError as e:
                    self.log.error(f"GMCP JSON解析错误: {e}")
            else:
                self.log.warning(f"无法解析GMCP格式: {gmcp_str}")
                
        except Exception as e:
            self.log.error(f"处理GMCP数据时出错: {e}")

    def _handle_move_data(self, data):
        """
        处理GMCP.Move数据
        
        Args:
            data (dict): 解析后的移动数据
        """
        self.log.debug(f"处理移动数据: {data}")
        # 在这里可以添加具体的移动数据处理逻辑
        # 例如更新用户界面显示当前位置、可行走的方向等


class MUDTelnetWriter(ExtensionWriter, telnetlib3.TelnetWriter):
    """
    MUD客户端的Telnet写入器无编码类
    继承TelnetWriter外壳，主要实现依赖ExtensionWriter
    """
    def __init__(self, *args, **kwargs):
        # 初始化父类
        super().__init__(*args, **kwargs)
        # MCCP2压缩状态
        self.mccp2_compressing = False
        self.decompressor = None

    

class MUDTelnetWriterUnicode(ExtensionWriter, telnetlib3.TelnetWriterUnicode):
    """
    MUD客户端的Telnet写入器Unicode类
    继承TelnetWriterUnicode外壳，主要实现依赖ExtensionWriter
    """
    def __init__(self, *args, **kwargs):
        # 初始化父类
        super().__init__(*args, **kwargs)
        # MCCP2压缩状态
        self.mccp2_compressing = False
        self.decompressor = None
        self.log = logging.getLogger(__name__)
        self.log.setLevel(logging.DEBUG)